package com.itcs.app.tran;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.dubbo.common.json.ParseException;
import com.alibaba.fastjson.JSON;
import com.itcs.app.service.TransJournalService;
import com.itcs.app.util.PayResult;
import com.itcs.app.util.PayStatus;
import com.itcs.app.util.PayType;
import com.itcs.app.util.StringUtils;
import com.itcs.box.BoxConstants;
import com.itcs.box.domain.BoxData;
import com.itcs.box.domain.BoxRequest;
import com.itcs.box.domain.BoxResponse;
import com.itcs.box.util.BoxResUtils;
import com.itcs.box.util.LogUtils;
import com.itcs.dubbo.service.DubboServiceAdapter;
import com.itcs.rongyun.rongsdk.Response;
import com.itcs.rongyun.rongsdk.RunRongPublishSystemMessage3;
import com.itcs.trading.mapper.ExitWhitelistOpHisMapper;
import com.itcs.trading.mapper.TerminalInfoMapper;
import com.itcs.trading.mapper.TransJournalMapper;
import com.itcs.trading.mapper.UserAccountInfoMapper;
import com.itcs.trading.mapper.UserAccountOpHisMapper;
import com.itcs.trading.mapper.UserInfoMapper;
import com.itcs.trading.model.ExitWhitelistOpHis;
import com.itcs.trading.model.TerminalInfo;
import com.itcs.trading.model.TransJournal;
import com.itcs.trading.model.UserAccountInfo;
import com.itcs.trading.model.UserAccountOpHis;
import com.itcs.trading.model.UserInfo;

/**
 * 通行费支付请求 自有钱包使用1007交易
 * 
 * @author LiuPeng
 * @date 2017年12月9日
 * 
 */
@Component
public class BoxTran1007 implements DubboServiceAdapter {

	private Log logger = LogFactory.getLog(getClass());
	// 白名单
	@Autowired
	private ExitWhitelistOpHisMapper exitWhitelistOpHisMapper;

	@Autowired
	private TransJournalMapper transJournalMapper;
	@Autowired
	private TransJournalService transJournalService;

	@Autowired
	private UserInfoMapper userInfoMapper;

	@Autowired
	private UserAccountInfoMapper userAccountInfoMapper;

	@Autowired
	private UserAccountOpHisMapper userAccountOpHisMapper;
	
	@Autowired
	private TerminalInfoMapper terminalInfoMapper;

	@Override
	public String getTrancode() {
		return "box_1007";
	}

	public String getTranDescription() {
		return "APP支付请求";
	}

	@Override
	public Map<String, Object> exchange(Map<String, Object> reqRecord) {

		logger.info(LogUtils.build(getTrancode(), getTranDescription(), "接收APP支付请求", JSON.toJSONString(reqRecord)));

		Map<String, Object> res = new HashMap<>();
		try {
			BoxRequest boxRequest = (BoxRequest) reqRecord.get(BoxConstants.BOX_REQ_KEY);

			BoxResponse boxResponse = appkk(boxRequest);

			res.put(BoxConstants.BOX_RES_KEY, boxResponse);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return res;
	}

	/**
	 * APP扣款
	 * 
	 * @param requestInfo
	 * @return
	 * @throws ParseException
	 */
	private BoxResponse appkk(BoxRequest requestInfo) throws ParseException {

		BoxResponse responseInfo = null;
		BoxData data = requestInfo.getData();
		String deviceId = data.getDeviceId();
		try {

			BoxData responseData = new BoxData();

			responseData.setDeviceId(deviceId);
			responseData.setTransacSeq(data.getTransacSeq());
			responseData.setReplyTime(String.valueOf(new Date().getTime()));

			// 1、收到交易请求（车牌/订单号/金额/通讯ID）
			String carPlate = data.getCarPlate();
			String transacSeq = data.getTransacSeq();
			String tollFare = data.getTollFare();

			if (StringUtils.isEmpty(carPlate)) {
				responseInfo = BoxResUtils.build2008(data, PayResult.其他, PayType.BOX_APP支付, null, data.getInvoice());
				logger.info(LogUtils.build(getTrancode(), getTranDescription(),
						"车牌号为空,app支付失败:" + transacSeq + ",CarPlate:" + carPlate));
				return responseInfo;
			}
			// 存储以分为单位
			BigDecimal balance = new BigDecimal(tollFare);

			// 2、通过车牌查找白名单
			ExitWhitelistOpHis ewoh = new ExitWhitelistOpHis();
			ewoh.setCarPlate(carPlate);
			List<ExitWhitelistOpHis> exitWhitelistOpHiss = exitWhitelistOpHisMapper.findByWhitelist(ewoh);
			if (exitWhitelistOpHiss.size() < 1) {
				logger.info(LogUtils.build(getTrancode(), getTranDescription(),
						"白名单已清空：" + transacSeq + ",CarPlate:" + carPlate));
				responseInfo = BoxResUtils.build2008(data, PayResult.其他, PayType.BOX_APP支付, null, data.getInvoice());
				return responseInfo;
			}

			// 先查询是否已经进行过支付，生成订单
			boolean ispay = false;// 是否被支付

			TransJournal traderecords = transJournalService.selectByTransNo(transacSeq);
			if (traderecords == null || traderecords.getTransNo() == null) {
				traderecords = new TransJournal(transacSeq, balance, Long.parseLong(deviceId), PayType.自由钱包,
						data.getRequestTime());
				traderecords.setCarPlate(carPlate);
				// 将订单写入到数据库
				transJournalMapper.insert(traderecords);
			} else if (traderecords.getPayState() == 2 || traderecords.getPayState() == 5) {
				//修改为支付成功，清空白名单==================2018-04-20
				// 11、清空某车牌的白名单
				ExitWhitelistOpHis clear = new ExitWhitelistOpHis();
				clear.setCarPlate(carPlate);
				exitWhitelistOpHisMapper.deleteWhitelis(clear);
				logger.info("删除已支付车牌白名单,车牌号为["+carPlate+"]");
				//修改为支付成功，清空白名单==================2018-04-20
				// 已支付
				responseInfo = BoxResUtils.build2008(data, PayResult.其他, PayType.BOX_APP支付, null, data.getInvoice());
				logger.info(LogUtils.build(getTrancode(), getTranDescription(), "订单已被支付，流程中止" + transacSeq));
				return responseInfo;
			}

			// 生成使用列表
			List<Map<String, Object>> userList = new ArrayList<Map<String, Object>>();

			for (ExitWhitelistOpHis ExitWhitelistOpHis : exitWhitelistOpHiss) {// 逐条遍历
				// 4、通过白名单获取USER-ID，获取金额。。
				// user_account_info
				UserAccountInfo userAccountInfo = userAccountInfoMapper
						.selectByPrimaryKey(ExitWhitelistOpHis.getUserId());
				UserInfo userInfo = userInfoMapper.selectByPrimaryKey(ExitWhitelistOpHis.getUserId());
				BigDecimal oldBalance = userAccountInfo.getAccountBalance();// 金额
				Map<String, Object> hso = new HashMap<String, Object>();
				hso.put("userAccountInfo", userAccountInfo);
				hso.put("userInfo", userInfo);
				userList.add(hso);

				userInfo.getDeviceAppNo();

				logger.info(LogUtils.build(getTrancode(), getTranDescription(), "出口白名单记录,payMethod:"
						+ userInfo.getPayMethod() + ",oldBalance:" + oldBalance + ",balance:" + balance));

				// 5、判断是否满足扣款条件，已被支付、是否自动扣款，金额小
				if (ispay) {
					userAccountInfo.setAccountState(PayStatus.Account_已支付);
					continue;
				}
				if (userInfo.getPayMethod() != 2) {
					userAccountInfo.setAccountState(PayStatus.Account_非自动扣款);
					continue;
				}

				if (oldBalance.compareTo(balance) >= 0) {
					// 自动扣款
					// 6、判断交易是否支付，没有则直接扣款
					BigDecimal endBalance = oldBalance.subtract(balance);

					userAccountInfo.setAccountBalance(endBalance);// 进行扣款
					// user.setUpdateTime(new Date());
					userAccountInfoMapper.payBalance(userAccountInfo);

					// 临时标记用户支付情况，不存储数据库
					userAccountInfo.setAccountState(PayStatus.支付成功);
					ispay = true;// 已支付

					logger.info(LogUtils.build(getTrancode(), getTranDescription(),
							"APP支付自动扣款成功。transacSeq：" + transacSeq + ",UserId:" + userAccountInfo.getUserId() + ",余额变动["
									+ oldBalance + "->" + endBalance + "]"));
					//修改为支付成功，清空白名单==================2018-04-20
					// 11、清空某车牌的白名单
					ExitWhitelistOpHis clear = new ExitWhitelistOpHis();
					clear.setCarPlate(carPlate);
					exitWhitelistOpHisMapper.deleteWhitelis(clear);
					logger.info("删除已支付车牌白名单,车牌号为["+carPlate+"]");
					//修改为支付成功，清空白名单==================2018-04-20

					// 加事务
					traderecords.setPayState(PayStatus.支付成功);// 更新订单状态
					traderecords.setPayerId(PayType.自由钱包);// 于斌2018年1月15日21:10:51 加入支付状态
					traderecords.setUserId(userInfo.getUserId());
					transJournalMapper.updateByPrimaryKey(traderecords);
					// TransJournal.pay;
					// =============================账户历史变动表================================
					// 6、将数据插入的账户历史变动表中?????????,需记录到记录表串
					UserAccountOpHis userAccountOpHis = new UserAccountOpHis();
					userAccountOpHis.setTransNo(transacSeq);
					userAccountOpHis.setTransTimestamp(new Date());
					userAccountOpHis.setUserId(userInfo.getUserId());// 用户ID
					userAccountOpHis.setChangeBalance(balance);// 消费
					userAccountOpHis.setOldBalance(oldBalance);// 期初余额
					userAccountOpHis.setNowBalance(endBalance);// 期末余额
					userAccountOpHis.setResume("通讯盒：" + deviceId);
					userAccountOpHisMapper.insert(userAccountOpHis);
					// ==========================账户历史变动表===================================

					// 下发2008，通知车道抬杠
					responseInfo = BoxResUtils.build2008(data, PayResult.成功, PayType.BOX_APP支付, null,
							data.getInvoice());
					logger.info(LogUtils.build(getTrancode(), getTranDescription(), "APP支付请求返回2008应答",
							JSON.toJSONString(responseInfo)));
					break;
				} else {
					userAccountInfo.setAccountState(PayStatus.Account_余额不足);
				}
			}

			// 10、分类通知手机APP
			// 某订单，已扣款，而且是当前
			// 已被支付，如果设置为自动扣款，余额不足
			// 支付失败
			// 寻找异常
			for (Map<String, Object> userMap : userList) {
				UserAccountInfo userAccountInfo = (UserAccountInfo) userMap.get("userAccountInfo");
				UserInfo userInfo = (UserInfo) userMap.get("userInfo");
				Long userId = userAccountInfo.getUserId();
				Integer state = userAccountInfo.getAccountState();
				StringBuffer mess = new StringBuffer(
						"订单号:" + transacSeq + ",车牌号:" + carPlate + ",通行费:" + tollFare + "。");
				if (ispay) {// 当前付款人
					if (state == PayStatus.支付成功) {
						mess.append("支付成功");
						
						//修改为支付成功，清空白名单==================2018-04-20
						// 11、清空某车牌的白名单
						ExitWhitelistOpHis clear = new ExitWhitelistOpHis();
						clear.setCarPlate(carPlate);
						exitWhitelistOpHisMapper.deleteWhitelis(clear);
						logger.info("删除已支付车牌白名单,车牌号为["+carPlate+"]");
						//修改为支付成功，清空白名单==================2018-04-20
						
						// 通知只发送给支付成功的人。
						Response response = Response.APP_NOTIFICATION_SUCCESS(userId);
						RunRongPublishSystemMessage3 runRong = new RunRongPublishSystemMessage3(userInfo.getDeviceAppNo(),
								mess.toString(), response);
						runRong.pushThread();
						
					} else if (state == PayStatus.Account_余额不足) {// 其它付款人，并且余额不足
						mess.append("已被支付,余额不足");
					} else {
						mess.append("已被支付");
					}
					
				} else {
					mess.append("待支付");// 需跳转到指定支付界面，，寻问李磊
					
					// 设置出口信息，从通讯盒表中查询出口信息
					TerminalInfo terminalInfo = terminalInfoMapper.selectByPrimaryKey(Long.parseLong(deviceId));
					traderecords.seteLaneId(terminalInfo.getLaneId());
					traderecords.seteTollPlazaId(terminalInfo.getTollPlazaId());
					traderecords.seteStationId(terminalInfo.getStationId());
					
					Response response = Response.APP_NOTIFICATION_DETAIL(traderecords);
					// 将订单信息发送给客户端
					RunRongPublishSystemMessage3 runRong = new RunRongPublishSystemMessage3(userInfo.getDeviceAppNo(),
							mess.toString(), response);
					runRong.pushThread();
				}
			}

			/*// 11、清空某车牌的白名单
			ExitWhitelistOpHis clear = new ExitWhitelistOpHis();
			clear.setCarPlate(carPlate);
			exitWhitelistOpHisMapper.deleteWhitelis(clear);*/
			
			logger.info(LogUtils.build(getTrancode(), getTranDescription(), "APP支付请求处理完成"));
		} catch (Exception ex) {
			responseInfo = BoxResUtils.build2008(data, PayResult.其他, PayType.BOX_APP支付, null, data.getInvoice());
			logger.error(LogUtils.build(getTrancode(), getTranDescription(), "APP支付请求处理异常,返回2008," + ex.getMessage(),
					JSON.toJSONString(requestInfo)));
		}
		return responseInfo;
	}
}